package com.heima.wemedia.listener;

import com.heima.api.feign.aparticle.ApArticleFeignClient;
import com.heima.common.constants.DelayConstants;
import com.heima.common.redis.RedisCacheService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 发布延迟消息消费者
 *
 * @Author mr.luo
 * @Date 25 6月 2025 22:44
 */
@Component
@Slf4j
public class WnMaterialDelayMessageListener {
    @Autowired
    private ApArticleFeignClient apArticleFeignClient;
    @Autowired
    private RedisCacheService redisCacheService;
    private static final String DELAY_WNMATERIAL_KEY = "wnmaterial:PublishAnArticle";
    @Autowired
    private WmNewsService wmNewsService;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = DelayConstants.DELAY_WNMATERIAL_QUEUE_NAME, durable = "true"
                    , arguments = {
                    @Argument(name = "x-dead-letter-exchange", value = "error.direct"),
                    @Argument(name = "x-dead-letter-routing-key", value = "error")
            }),
            exchange = @Exchange(name = DelayConstants.DELAY_EXCHANGE_NAME, delayed = "true"),
            key = DelayConstants.DELAY_WNMATERIAL_KEY
    ))   //  指定错误处理器
    public void PublishArticleOnMessage(ArticleDto dto) {
        String token = null;
        String key = DELAY_WNMATERIAL_KEY + ":" + dto.getAuthorId() + ":" + System.currentTimeMillis() / 1000;
        try {
            log.info("延迟消息消费者，发布文章: {}", dto);
            token = redisCacheService.tryLock(key, 60);
            if (token == null) {
                throw new RuntimeException("请勿重复提交");
            }
            //进行健壮性判断，降低幂等率
            if (dto.getAuthorId() == null) {
                throw new RuntimeException("文章id不能为空");
            }
//            if (true){
//                throw new RuntimeException("请勿重复提交");
//            }
            //查询文章,此时的文章是否存在，并且状态为审核通过但是未发布
            WmNews wmNews = wmNewsService.lambdaQuery()
                    .eq(WmNews::getTitle, dto.getTitle())
                    .eq(WmNews::getType, dto.getLayout())
                    .eq(WmNews::getChannelId, dto.getChannelId())
                    .eq(WmNews::getStatus, WmNews.Status.SUCCESS.getCode())
                    .eq(WmNews::getUserId, dto.getAuthorId())
                    .eq(WmNews::getContent, dto.getContent())
                    .one();
            if (wmNews == null || !wmNews.getStatus().equals(WmNews.Status.SUCCESS.getCode())) {
                log.error("文章不存在或审核不通过");
                throw new RuntimeException("文章不存在或审核不通过");
            }
            //再次进行校验，看时间是否达到发布时间
            //发布到手机端
            if (wmNews.getStatus() == WmNews.Status.SUCCESS.getCode() && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
                //发布到手机端
                ResponseResult responseResult = apArticleFeignClient.save(dto);
                if (null != responseResult && responseResult.getCode().equals(200)) {
                    //保存成功
                    wmNews.setArticleId((Long) responseResult.getData());
                    //修改文章状态为已发布
                    wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
                    boolean b = wmNewsService.updateById(wmNews);
                    if (!b) {
                        throw new RuntimeException("修改文章状态失败");
                    }
                    log.info("延迟队列发送信息成功，文章发布成功");

                } else {
                    //保存失败
                    throw new RuntimeException("保存app端文章失败");
                }
            } else {
                log.error("文章发布时间未到，或审核不通过");
                throw new RuntimeException("文章发布时间未到，或审核不通过");
            }

        } catch (Exception e) {
            log.error("延迟队列发送信息失败", e);
            throw new RuntimeException("延迟队列发送信息失败");
        } finally {
            log.info("延迟队列发送信息结束，释放redis锁");
            redisCacheService.unlock(key, token);
        }
    }
}
